package princessWorld;

import processing.core.*;

public class Critters {
	
	PApplet p;
	
	int critterNum = 120;
	private Critter[] critters = new Critter[critterNum];
	
	PVector critterCenter;
	
	public void setup(PApplet processing) {
		p = processing;

		critterCenter = new PVector();
		for(int i = 0; i < critterNum; i ++) {
			critters[i] = new Critter();
			critters[i].setup(p);
			critterCenter.add(critters[i].getPosition());
		}
		
		
	}
	
	public void update() {
		//Critter flock behavior
		PVector ruleSum = new PVector();
		PVector v1 = new PVector();
		PVector v2 = new PVector();
		PVector v3 = new PVector();
		PVector v4 = new PVector();
		for(int i = 0; i < critterNum; i ++) {
			
			v1 = moveTowardsCenter(critters[i]);
			ruleSum.add(v1);
			
			v2 = avoidCollision(critters[i]);
			ruleSum.add(v2);
			
			v3 = matchVelocity(critters[i]);
			ruleSum.add(v3);
			
			v4 = checkBoundaries(critters[i]);
			ruleSum.add(v4);
			
			
			critters[i].update(v1);
		}
		
	}
	
	public void draw() {
		for(int i = 0; i < critterNum; i ++) {
			critters[i].draw();
		}
	}
	
	private PVector moveTowardsCenter(Critter critter) {
		PVector vector = new PVector();
		
		//Get center of all boids
		critterCenter.set(0, 0, 0);
		float minDist = 150f;
		int centerCount = 0;
		for(int i = 0; i < critterNum; i ++) {
			if(!critters[i].equals(critter) && critters[i].getPosition().dist(critter.getPosition()) < minDist) {
				critterCenter.add(critters[i].getPosition());	
				centerCount++;
			}
		}
		//Divide by the number of critters 
		critterCenter.mult(1f / (float) centerCount);
		
		
		//Subtract critter position from center to get a vector towards the center
		vector.set(critterCenter);
		vector.sub(critter.getPosition());
		
		//Scale the vector to 1% 
		vector.mult(1f / 3000f);
		
		return vector;
	}
	
	private PVector avoidCollision(Critter critter) {
		PVector vector = new PVector();
		float minDist = 30f;
		
		for(int i = 0; i < critterNum; i ++) {
			if(!critter.equals(critters[i])) {
				float dist = critter.getPosition().dist(critters[i].getPosition());
				
				if (dist < minDist) {
					vector = PVector.sub(critter.getPosition(), critters[i].getPosition());
					vector.mult(1f / (minDist * 2f));
				}
			}
		}
		
		return vector;
	}
	
	private PVector matchVelocity(Critter critter) {
		PVector vector = new PVector();

		float minDist = 150f;
		for(int i = 0; i < critterNum; i ++) {
			if(!critters[i].equals(critter) && critters[i].getPosition().dist(critter.getPosition()) < minDist) {
				vector.add(critters[i].getVelocity());	
			}
		}
		//vector.mult(10f);
		
		
		return new PVector();
	}
	
	//Boundaries
	private PVector checkBoundaries(Critter critter) {
		PVector vector = new PVector();
		
		float repelBoundary = 20f;
		float repelVelocity = 10f;
				
		float xPos = critter.getPosition().x;
		float yPos = critter.getPosition().y;
		float zPos = critter.getPosition().z;
		
		if(xPos < 0 + repelBoundary) {
			vector.x = repelVelocity;
		} else if (xPos > IPrincessWorld.SIZE.x - repelBoundary) {
			vector.x = -repelVelocity;
		}

		if(yPos < 0 + repelBoundary) {
			vector.y = repelVelocity;
		} else if (yPos > IPrincessWorld.SIZE.y - repelBoundary) {
			vector.y = -repelVelocity;
		}

		if(zPos > 0) {
			vector.z = -repelVelocity;
		} else if (zPos < IPrincessWorld.SIZE.z) {
			vector.z = +repelVelocity;
		}
		
		return vector;
	}

}
